<template>
  <div class="FL-container getting-started">
    <!-- 画布 -->
    <div class="app-content" ref="logicFlowContainerRef"></div>
    <!-- 属性面板 -->
    <el-drawer title="设置节点属性" v-model="dialogVisible" direction="rtl" size="900px" :before-close="closeDialog">
      <PropertyDialog v-if="dialogVisible" :nodeData="clickNode" :lf="lf as LogicFlow" @setPropertiesFinish="closeDialog" :readonly="true"></PropertyDialog>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import LogicFlow, {BaseEdgeModel, BaseNodeModel} from "@logicflow/core";
import "@logicflow/core/lib/style/index.css";
import '@logicflow/extension/lib/style/index.css';
import {ref} from "vue";
import {setTheme} from "/@/components/gFlow/config";

import {
  registerEnd,
  registerStart,
  registerStartDone,
  registerConcurrent,
  registerPush,
  registerCondition,
  registerUserTask, registerEdgeDone, registerConditionDone, registerEndDone, registerConcurrentDone, registerPushDone
} from "/@/components/gFlow/registerNode";
import PropertyDialog from "/@/components/gFlow/propertySetting/PropertyDialog.vue";
import {getNodeData} from "/@/api/flow/flowModel";
import {
  FlowCheckRuleDept,
  FlowCheckRuleDeptLeader, FlowCheckRulePost,
  FlowCheckRuleRole,
  FlowCheckRuleUser
} from "/@/components/gFlow/consts";
import registerUserTaskDone from "./registerNode/registerUserTaskDone";

defineOptions({ name: "ShowFlowDesign"})
const modelId = ref(0)
const nodeId = ref('')
const logicFlowContainerRef = ref()
const lf = ref<LogicFlow>({} as LogicFlow)
const addPanelStyle = ref({
  top: '0',
  left: '0',
})
const showAddPanel = ref(false)
const addClickNode = ref<any>()
const clickNode = ref({})
const dialogVisible = ref(false)
const moveData = ref({})

const showDesign = (params:any)=>{
  modelId.value = params.flowId
  nodeId.value = params.processId
  lf.value = new LogicFlow({
    container: logicFlowContainerRef.value,
    grid: false,
  })
  registerNode()
  initLF()
}
//注册节点信息
const registerNode = ()=>{
  const logicFlow = lf.value as LogicFlow
  registerStart(logicFlow)
  registerStartDone(logicFlow)
  registerEnd(logicFlow)
  registerEndDone(logicFlow)
  registerConcurrent(logicFlow)
  registerConcurrentDone(logicFlow)
  registerPush(logicFlow)
  registerPushDone(logicFlow)
  registerCondition(logicFlow)
  registerConditionDone(logicFlow)
  registerUserTask(logicFlow)
  registerUserTaskDone(logicFlow)
  registerEdgeDone(logicFlow)
}
const initLF= async ()=>{
  const logicFlow = lf.value as LogicFlow;
  setTheme(logicFlow)
  await $_render()
  $_LfEvent()
  //nodeId.value = 'f4330b11-25ff-4ced-b011-9730bf1be122' //测试用
  //设置已经处理过的节点状态
  if(nodeId.value!='') {
    /*lf.value.getNodeOutgoingEdge(nodeId.value).map((edge: BaseEdgeModel) => {
      lf.value.changeEdgeType(edge.id, "edgeDone")
    })
    const data = lf.value.getNodeDataById(nodeId.value)
    lf.value.changeNodeType(nodeId.value,data?.type+"Done")*/
    setDonePrevNode(nodeId.value)
  }
}
const setDonePrevNode = (nodeId:string)=>{
  lf.value.getNodeIncomingNode(nodeId).map((node:BaseNodeModel)=>{
    if(node.type.indexOf("Done")>=0){
      return
    }
    lf.value.changeNodeType(node.id,node.type+"Done")
    lf.value.getNodeOutgoingEdge(node.id).map((edge: BaseEdgeModel) => {
      lf.value.changeEdgeType(edge.id, "edgeDone")
    })
    setDonePrevNode(node.id)
  })
}
const $_render = async ()=>{
  //获取节点数据
  return getNodeData(modelId.value).then((res:any)=>{
    const nodes = (res.data.nodes??[]).map((item:any)=>{
      const node = {
        id: item.nodeId,
        type: item.nodeType,
        x: item.nodePosition.x,
        y: item.nodePosition.y,
        text: item.nodeText??{},
        properties: {
          text: item.nodeText?.value,
          actionRule: item.nodeActionRule,
          approveRule: item.nodeRule,
          notice: item.notice ?? [],
          rollback: item.rollback,
          nodeExt: item.nodeExt??[]
        }
      }
      setReceiver(node,item.nodeReceiver)
      return node
    })
    const edges = (res.data.edges??[]).map((item:any)=>{
      return {
        id: item.id,
        type: item.lineType,
        sourceNodeId: item.sourceNodeId,
        targetNodeId: item.targetNodeId,
        startPoint:item.startPoint,
        endPoint:item.endPoint,
        properties: item.properties,
        pointsList: item.pointsList,
        text:item.text
      }
    })
    lf.value.render({nodes,edges});
    $_LfEvent();
  })
}
const setReceiver = (node:any,receivers:Array<string>)=>{
  switch(node.properties.actionRule){
    case FlowCheckRuleRole://角色
      node.properties.roleIds = receivers
      break
    case FlowCheckRuleDept://部门
    case FlowCheckRuleDeptLeader://部门负责人
      node.properties.deptIds = receivers
      break
    case FlowCheckRuleUser://指定人员
      node.properties.userIds = receivers
      break
    case FlowCheckRulePost://岗位
      node.properties.postIds = receivers
  }
}

const $_LfEvent=()=>{
  const logicFlow = lf.value as LogicFlow;
  logicFlow.on('node:click', (data) => {
    console.log('node:click', data);
    clickNode.value = data.data;
    dialogVisible.value = true;
  })
  logicFlow.on('edge:click', ({ data }) => {
    console.log('edge:click', data);
    //this.$data.clickNode = data;
    //this.$data.dialogVisible = true;
  });
  logicFlow.on('element:click', () => {
    hideAddPanel();
  });
  logicFlow.on('edge:add', ({ data }) => {
    console.log('edge:add', data);
  });
  logicFlow.on('node:mousemove', ({ data }) => {
    console.log('node:mousemove');
    moveData.value = data;
  });
  logicFlow.on('blank:click', () => {
    hideAddPanel();
  });
  logicFlow.on('connection:not-allowed', (data) => {
    console.log('connection:not-allowed',data)
  });
  logicFlow.on('node:mousemove', () => {
    console.log('on mousemove');
  });
}
const hideAddPanel = () => {
  showAddPanel.value = false;
  addPanelStyle.value.top = '0';
  addPanelStyle.value.left = '0';
  addClickNode.value = null;
}
const closeDialog = () => {
  dialogVisible.value = false;
}
defineExpose({showDesign})
</script>

<style scoped lang="scss">
.FL-container {
  width: 100%;
  overflow: hidden;
  .app-content {
    height: calc(100vh - 120px);
  }
}
.demo-control{
  position: absolute;
  top: 20px;
  right: 50px;
  z-index: 2;
}
</style>
